package com.niiwoo.civet.trade.report.upload.util;

import com.niiwoo.civet.trade.report.upload.exception.DecryptDataException;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.DESedeKeySpec;



public class FileUtil {
	public boolean BJS_SymmEncFile(String srcfile, String destfile, byte[] key, long mode)
	  {
	    try
	    {
	      SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");

	      DESedeKeySpec keyspec = new DESedeKeySpec(key);
	      SecretKey deskey = keyfactory.generateSecret(keyspec);

	      InputStream in = new FileInputStream(srcfile);
	      OutputStream out = new FileOutputStream(destfile);

	      BufferedInputStream bufIn = new BufferedInputStream(in, 131072);
	      BufferedOutputStream bufOut = new BufferedOutputStream(out, 131072);

	      Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
	      cipher.init(1, deskey);

	      doEncryptAndDecrypt(bufIn, bufOut, cipher);

	      bufIn.close();
	      bufOut.close();
	      in.close();
	      out.close();

	      return true;
	    } catch (Exception e) {
	      //errorlog("Exception in using symmetric encryption to encrypt files!", e);
	      //debuglog("Exception in using symmetric encryption to encrypt files!");
	    }

	    return false;
	  }

	  public boolean BJS_SymmDecFile(String srcfile, String destfile, byte[] key, long mode)
	    throws DecryptDataException
	  {
	    try
	    {

	      SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");
	      DESedeKeySpec keyspec = new DESedeKeySpec(key);
	      SecretKey deskey = keyfactory.generateSecret(keyspec);

	      Cipher cpher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
	      cpher.init(2, deskey);

	      InputStream in = new FileInputStream(srcfile);
	      OutputStream out = new FileOutputStream(destfile);

	      BufferedInputStream bufIn = new BufferedInputStream(in, 131072);
	      BufferedOutputStream bufOut = new BufferedOutputStream(out, 131072);

	      doEncryptAndDecrypt(bufIn, bufOut, cpher);

	      bufIn.close();
	      bufOut.close();
	      in.close();
	      out.close();

	      return true;
	    } catch (Exception e) {
	      //errorlog("Exception in using symmetric decryption to decrypt files!", e);
	      //debuglog("Exception in Using symmetric decryption to decrypt files!");
	    }

	    return false;
	  }

	  public static void doEncryptAndDecrypt(InputStream in, OutputStream out, Cipher cipher)
	    throws IOException, IllegalBlockSizeException, BadPaddingException, ShortBufferException
	  {
	    int blockSize = 8192;
	    int outputSize = cipher.getOutputSize(blockSize);
	    byte[] inBytes = new byte[blockSize];
	    byte[] outBytes = new byte[outputSize];

	    int inLength = 0;
	    boolean more = true;

	    while (more) {
	      inLength = in.read(inBytes);
	      if (inLength == blockSize)
	      {
	        int outLength = cipher.update(inBytes, 0, blockSize, outBytes);

	        out.write(outBytes, 0, outLength);
	      } else {
	        more = false;
	      }
	    }
	    if (inLength > 0)
	      outBytes = cipher.doFinal(inBytes, 0, inLength);
	    else {
	      outBytes = cipher.doFinal();
	    }
	    out.write(outBytes);
	  }

	  public byte[] readFile(String file_path)
	  {
	    BufferedInputStream bins = null;
	    byte[] bfile = null;
	    String path = file_path;
	    try
	    {
	      bins = new BufferedInputStream(new FileInputStream(path), 1024);

	      if (bins.available() > 0) {
	        bfile = new byte[bins.available()];
	        bins.read(bfile);
	      }
	      bins.close();
	    } catch (IOException e) {
	    	e.printStackTrace();
	    }
	    finally
	    {
	      try
	      {
	        bins.close();
	      }
	      catch (IOException e) {
	        return null;
	      }
	    }

	    return bfile;
	  }

	  public void writeFile(byte[] bContent, String filePath)
	  {
	    BufferedOutputStream bouts = null;
	    try {
	      bouts = new BufferedOutputStream(new FileOutputStream(filePath), 1024);
	      bouts.write(bContent);
	      bouts.close();
	    } catch (IOException e) {
	      e.printStackTrace();
	    }
	    finally
	    {
	      try
	      {
	        bouts.close();
	      } catch (IOException e) {
	        //errorlog("IOException in closing writing file IO stream", e);
	        //debuglog("IOException in closing writing file IO stream");
	      }
	    }
	  }

}
